package blasthouse.states;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Vector;

import org.newdawn.slick.AngelCodeFont;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.gui.AbstractComponent;
import org.newdawn.slick.gui.ComponentListener;
import org.newdawn.slick.gui.MouseOverArea;
import org.newdawn.slick.gui.TextField;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

public class ConnectionState extends BasicGameState implements ComponentListener{
	private int stateID = -1;
	private Image background = null, connectImage = null;
	private TextField addressEntry = null, status = null, historyLabel = null;
	private Vector<TextField> addressHistory = new Vector<TextField>();
	private MouseOverArea connectButton = null, hostButton = null;
	private AngelCodeFont font = null;
	private BufferedReader is, inFromServer;
	private BufferedWriter os, outToServer;
	private boolean gotoHost = false;
	
	ConnectionState( int stateID ){ this.stateID = stateID; }
	
	@Override
	public int getID() { return 2; }

	@Override
	public void init(GameContainer container, StateBasedGame game) throws SlickException {
		// TODO setup game hosting, finding interface		
		try { 
			os = new BufferedWriter(new FileWriter("ips.txt", true));
			is = new BufferedReader(new FileReader("ips.txt"));
		} catch (FileNotFoundException e1) { e1.printStackTrace(); 
		} catch (IOException e) { e.printStackTrace(); }
		
		background = new Image("blasthouse/images/mainMenu.jpg");
		connectImage = new Image("blasthouse/images/connectButton.png");
		
		font = new AngelCodeFont("org/newdawn/slick/data/defaultfont.fnt", "org/newdawn/slick/data/defaultfont.png");
		
		addressEntry = new TextField(container, font, 0, 0, 150, 25);
		addressEntry.setLocation(100, 100);
		addressEntry.setBackgroundColor(Color.white);
		addressEntry.setTextColor(Color.black);
		
		Vector<String> list = new Vector<String>();
		String temp;
		
		// Constructs the list from memory
		try{
			while( (temp=is.readLine()) != null ){
				list.add(temp);
			}
		} catch(IOException e) { e.printStackTrace(); }
		
		int n = 15;
		for(int i = list.size()-1 ; i >= 0; i--){
			TextField marker = new TextField(container, font, 350, 100+(i*25), 150, 25);
			marker.setText(list.elementAt(i));
			marker.setBackgroundColor(Color.black);
			marker.setTextColor(Color.white);
			marker.setAcceptingInput(false);
			addressHistory.add(marker);
			n--;
			if( n == 0 ){ break; }
		}
		
		connectButton = new MouseOverArea(container, connectImage, 100, 150, this);
		hostButton = new MouseOverArea(container, connectImage, 100, 350, this);
	}

	@Override
	public void render(GameContainer container, StateBasedGame game, Graphics g) throws SlickException {
		// TODO render the stuff
		background.draw(0,0);
		addressEntry.render(container, g);
		connectButton.render(container, g);
		hostButton.render(container, g);
		
		for(TextField t : addressHistory){
			t.render(container, g);
		}
	}

	@Override
	public void update(GameContainer container, StateBasedGame game, int delta) throws SlickException {
		// TODO react to player clicks etc.
		// save IPs in a list, recall that list to populate on init, try connect for X seconds, scan an IP first?
		if( gotoHost ){
			game.enterState(BlastHouse.HOSTSTATE);
		}
	}

	@Override
	public void componentActivated(AbstractComponent source) {
		// TODO Add ip to list if it's unique, empty textfield, attempt connection
		if( source == connectButton ){
			String temp = addressEntry.getText();
		
			boolean invalid = false;
			
			temp = temp.trim();
			
			for(int i = 0; i < temp.length(); i++){
				if(temp.charAt(i) == '0' || temp.charAt(i) == '1' || temp.charAt(i) == '2' || 
						temp.charAt(i) == '3' || temp.charAt(i) == '4' || temp.charAt(i) == '5' || 
						temp.charAt(i) == '6' || temp.charAt(i) == '7' || temp.charAt(i) == '8' || 
						temp.charAt(i) == '9' || temp.charAt(i) == '.'){ }
				else{
					invalid = true;
					break;
				}
			}
			
			if( temp.length() < 7 ){ invalid = true; }
			
			if( !invalid ){ 
				record(temp);
				connect(temp);			
			}
			addressEntry.setText("");
		}
		if( source == hostButton ){
			System.out.println("hosting not implemented yet!");
			gotoHost = true;
		}
	}

	public void connect(String ip){
		// TODO hard stuff
		System.out.println("connecting...");
		Socket socketToServ;
		boolean connected = true;
		try {
			InetAddress serverAdd = InetAddress.getByName(ip);
			socketToServ = new Socket(serverAdd, 9876);
			outToServer = new BufferedWriter(new OutputStreamWriter(socketToServ.getOutputStream()));
			inFromServer = new BufferedReader(new InputStreamReader(socketToServ.getInputStream()));
		} catch (UnknownHostException e) { 
			connected = false;
			e.printStackTrace(); 
		} catch (IOException e) { 
			connected = false;
			e.printStackTrace(); 
		} finally{
			if( connected ){
				// TODO enter next state? lobby?
			}// TODO else update a status bar?
		}
	}
	
	public void record(String ip) {		
		Vector<String> list = new Vector<String>();
		String temp;
		
		// Constructs the list from memory
		try{
			while( (temp=is.readLine()) != null ){
				list.add(temp);
			}
		} catch(IOException e) { e.printStackTrace(); }
		
		// Searches the list(memory) for the current IP
		boolean found = false;
		for(String s : list){
			if( s.equalsIgnoreCase(ip) ){
				found = true;
				break;
			}
		}
		
		/*for(String s: list){
			try{
				os.write(s);
				os.newLine();
				os.flush();
			} catch(IOException e) { e.printStackTrace(); }
		}*/
		// If we don't have the IP in memory we record it in our history
		if( !found ){
			try{
				os.write(ip);
				os.newLine();
				os.flush();
			} catch(IOException e) { e.printStackTrace(); }
		}		
	}
}
